package com.hzit.cart.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.hzit.cart.api.domain.Item;
import com.hzit.cart.api.model.ItemVo;
import com.hzit.cart.interceptor.LoginInterceptor;
import com.hzit.cart.service.CartService;
import com.hzit.cart.service.IItemService;
import com.hzit.common.constant.HzitBusinessConstants;
import com.hzit.common.entity.LoginUser;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 类名：
 * 作者：WF
 * 功能：
 */
@Service
public class CartServiceImpl implements CartService {
	@Autowired
	private StringRedisTemplate redisTemplate;
	@Autowired
	private IItemService itemService;

	private static final String REDIS_TOKEN_KEY = "hzit:token:";
	//1. 添加到购物车
	@Override
	public void addCart(String id, Integer num) throws InvocationTargetException, IllegalAccessException {
		//1.1 根据sku商品的id查询出sku的商品
		Item item = itemService.getById(id);
		ItemVo vo = null;
		if(item != null){
			//1.2 根据大key(登录用户名),小key（sellerId +":" + id ）得到商品（字符串）
			HashOperations<String, String, String> operations = redisTemplate.opsForHash();
			//1.3 从ThreadLocal中获取用户名
			String login = getLogin();
			String s = operations.get(HzitBusinessConstants.CART_NAME + login, id );
			//1.1 如果redis中有此商品，修改传入的商品id对应的哪件商品的数量
			if(StrUtil.isNotBlank(s)){
				//1.1.1 得到商品
				vo = JSON.parseObject(s,ItemVo.class);
				//1.1.2 再修改redis商品数量
				vo.setBuyNum(vo.getBuyNum() + num);

			}else{ //1.2 如果redis中没有此商品，添加到redis中
				vo = new ItemVo();
				BeanUtils.copyProperties(vo,item);
				vo.setBuyNum(num);

			}
			//1.1.3 修改到redis中
			//① 如果最后购买的数量小于0，就从redis中删除它
			if(vo.getBuyNum() <= 0){
				operations.delete(HzitBusinessConstants.CART_NAME  + login,id);
			}else{ // ② 否则，就放到redis中
				operations.put(HzitBusinessConstants.CART_NAME  + login,id,JSON.toJSONString(vo));
			}
		}
	}
	private String getLogin() {
		// 1. 从线程本地变量取值
		LoginUser loginUser = LoginInterceptor.threadLocal.get();

		return loginUser.getLogin();
	}

	//2. 得到某个登录用户的所有的购物车信息
	@Override
	public Map<String, List<ItemVo>> getCartList() {
		//2.1 定义某个登录用户的购物车列表集合
		// BigDecimal bd1 = new BigDecimal(10);
		// BigDecimal bd2 = new BigDecimal(3);
		// BigDecimal multiply = bd1.multiply(bd2);    // 乘法
		// BigDecimal add = bd1.add(bd2);              // 加法
		// BigDecimal subtract = bd1.subtract(bd2);    // 减法
		// BigDecimal divide = bd1.divide(bd2);        // 除法


		HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
		//2.2 根据当前登录用户名，得到对应的hash的key的集合
		String login = getLogin();
		List<String> values = opsForHash.values(HzitBusinessConstants.CART_NAME + login);
		//2.3 使用lamba表达式 + stream流式编程技术完成数据的处理： （新的技术实现）
		Map<String, List<ItemVo>> mapList = values.stream()
				.map(m -> JSON.parseObject(m, ItemVo.class))
				.collect(Collectors.toList())
				.stream()
				.collect(Collectors.groupingBy(ItemVo::getSeller, Collectors.toList()));
		System.out.println("mapList = " + mapList);

		// 原始处理方法（旧的方法）
		//2.3 将hash的key中的商家id查询放到下面的集合中
		// Set<String> sellerIdSet = new HashSet<>();  // 去重所有商家id集合
		// for (String key : keys) {
		// 	String[] split = key.split(":");
		// 	sellerIdSet.add(split[0]);
		// }
		// //2.4 再一次遍历所有的key的集合，在其中判断
		// for (String key : keys) {
		// 	List<ItemVo> itemVos = new ArrayList<>();
		// 	for (String k : sellerIdSet) {
		// 		//2.4.1 判断在大key中是否有小k，如果有就取得此大key对应的哪条数据
		// 		if(key.contains(k)){
		// 			//2.4.2 根据name和大key得到哪条数据
		// 			String s = opsForHash.get(name, key);
		// 			//2.4.3 将此字符串数据转换为itemVo即可
		// 			ItemVo itemVo = JSON.parseObject(s, ItemVo.class);
		// 			//2.4.4 将此数据放到List集合
		// 			itemVos.add(itemVo);
		// 			//2.4.5 将list集合放到map集合
		// 			listMap.put(k,itemVos);
		// 		}
		// 	}
		// }

		//2.5 重新整理数据
		return mapList;
	}

	//3. 从redis中删除购物车
	@Override
	public Map<String, List<ItemVo>> removeCart(String id,String sellerId) throws InvocationTargetException, IllegalAccessException {
		//3.1 从redis中删除指定key的购物项信息
		HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
		//3.2 恢复库存 （改库存应该在提交订单成功后完成）
		//3.2.0 从ThreadLocal中获取登录用户
		String login = getLogin();
		opsForHash.delete(HzitBusinessConstants.CART_NAME + login,id);
		//3.3 重新查询得到redis数据
		return getCartList();
	}

	//4. 根据商品id查询出商品
	@Override
	public ItemVo getItemById(String skuId,Integer buyNum) throws InvocationTargetException, IllegalAccessException {
		Item item = itemService.getById(skuId);
		ItemVo vo = new ItemVo();
		BeanUtils.copyProperties(vo,item);
		vo.setBuyNum(buyNum);
		return vo;
	}

	//5. 生成token并放到redis中
	@Override
	public String createTokenToRedis() {
		//3.1 生成一个随机的token值
		String token = UUID.randomUUID().toString().replace("-", "");
		//3.2 将生成的token放到redis中
		//3.2.1 定义redis的key
		String key = REDIS_TOKEN_KEY + LoginInterceptor.threadLocal.get().getLogin();
		//3.2.2 将生成的token放到redis中
		redisTemplate.opsForValue().set(key,token,30, TimeUnit.MINUTES);       // 30分钟有效期

		return token;
	}
}
